package com.thghh.bcode.compiler;

import javax.tools.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Zhikang.Peng
 * @version 1.0
 * @email thghh@qq.com
 * @date 2020/12/17 16:44
 */
public class JavacJavaCompiler implements DynamicJavaCompiler {

    private ByteCodeFileManager fileManager;
    private JavaCompiler compiler;
    private DiagnosticCollector<JavaFileObject> diagnostics;

    public JavacJavaCompiler() {
        compiler = getCompiler();
        diagnostics = new DiagnosticCollector<>();
        fileManager = new ByteCodeFileManager(compiler.getStandardFileManager(diagnostics, null, null));
    }

    protected JavaCompiler getCompiler() {
        return ToolProvider.getSystemJavaCompiler();
    }

    @Override
    public boolean javaCompiler(String className, String sourceCode) {
        List<JavaFileObject> compilationUnits = new ArrayList<>();
        compilationUnits.add(new StringJavaFileObject(className, sourceCode));
        JavaCompiler.CompilationTask compilationTask = compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits);
        boolean result = compilationTask.call();
        for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
            System.out.format("Error on line %d in %s", diagnostic.getLineNumber(), diagnostic.getMessage(null));
        }
        return result;
    }

    @Override
    public Class loadClass(String className) throws ClassNotFoundException {
        return fileManager.getClassLoader(StandardLocation.CLASS_OUTPUT).loadClass(className);
    }

    @Override
    public byte[] getByteCode() {
        return fileManager.getByteCode();
    }

    @Override
    public void close() throws IOException {
        this.fileManager.close();
    }
}
